package cn.itcast.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;


/**
 * @program: springbootdemo
 * @description: 文件操作工具类
 * @author: wxk
 * @create: 2020-12-22 11:00
 **/
public class FileUtil {

	/**
	 * <li>功能描述：写文件
	 * 
	 * @param path
	 *            String 路径
	 * @param source
	 *            String 源文件
	 * @param filepre
	 *            String 目的文件
	 * @author wxk
	 */
	public static void writeFile(String path, String source, String filepre) {
		try {
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(path + "\\" + filepre), "UTF-8"));
			out.write(source);
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}// 将字节一个个写入文件

	}

	/**
	 * <li>功能描述：创建文件夹
	 * 
	 * @param baseDir
	 *            String 路径
	 * @param cssStyle
	 *            String CSS文件夹ID号
	 * @author wxk
	 */
	public static void mkDir(String baseDir, String cssStyle) {
		if (baseDir == null) {
			System.out.println("无法访问存储目录！");
			return;
		}
		File fUploadDir = new File(baseDir);
		if (!fUploadDir.exists()) {
			if (!fUploadDir.mkdir()) {
				System.out.println("无法创建存储目录！"); // 如果upload文件夹不存在，用于创建该文件夹
				return;
			}
		}
		String filePath = baseDir + "\\" + cssStyle;
		File f = new File(filePath);
		if (!f.exists()) {
			if (!f.mkdir()) {
				System.out.println("无法创建存储目录！"); // 如果upload文件夹不存在，用于创建该文件夹
				return;
			}
		}
	}

	/**
	 * <li>功能描述：创建文件夹
	 * 
	 * @param baseDir
	 *            String 路径
	 * @author wxk
	 */
	public static void mkHtmlFolder(String baseDir) {
		if (baseDir == null) {
			System.out.println("无法访问存储目录！");
			return;
		}
		File fUploadDir = new File(baseDir);
		if (!fUploadDir.exists()) {
			if (!fUploadDir.mkdir()) {
				System.out.println("无法创建存储目录！"); // 如果upload文件夹不存在，用于创建该文件夹
				return;
			}
		}
	}

	/**
	 * <li>功能描述：读取文件内容
	 * 
	 * @param path
	 *            String 文件存放路径
	 * @return String 文件内容字符串
	 * @author wxk
	 */
	public static String read(String path) {

		StringBuffer sb = new StringBuffer("");
		try {
			// FileReader reader = new FileReader(path);
			InputStreamReader isr = new InputStreamReader(new FileInputStream(
					path), "UTF-8");
			BufferedReader br = new BufferedReader(isr);
			String s = null;
			while ((s = br.readLine()) != null) {
				sb.append(s + '\n');
			}
			br.close();
			isr.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	/**
	 * <li>功能描述：读取文件内容
	 * 
	 * 
	 * 
	 * @param path
	 *            String 文件存放路径
	 * @return String 文件内容字符串
	 * @author wxk
	 */
	public static String readCss(String path) {

		StringBuffer sb = new StringBuffer("");
		try {
			InputStreamReader reader = new InputStreamReader(new FileInputStream(
					path), "UTF-8");
			BufferedReader br = new BufferedReader(reader);
			String s = null;
			br.readLine();
			while ((s = br.readLine()) != null) {
				sb.append(s + '\n');
			}
			br.close();
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	/**
	 * <li>功能描述：写文件
	 * 
	 * @param path
	 *            String 文件的路径
	 * @param content
	 *            String 写入文件的内容
	 * @author wxk
	 */
	public static void writerText(String path, String content) {
		try {
			BufferedWriter bw1 = new BufferedWriter(new FileWriter(path));
			bw1.write(content);
			bw1.flush();
			bw1.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 追加文件：使用FileOutputStream，在构造FileOutputStream时，把第二个参数设为true
	 * 
	 * @param fileName
	 *            String 文件名
	 * @param content
	 *            String 内容
	 * @author wxk
	 */
	public static void appandText(String fileName, String content) {
		BufferedWriter out = null;
		try {
			out = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(fileName, true)));
			out.write(content);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * <li>功能描述：从css文件中读取得到风格名称
	 * 
	 * @param path
	 *            String css文件的存放路径
	 * @return result String css的风格名称
	 * @throws Exception
	 * @author wxk
	 */
	public static String getStyleName(String path) throws Exception {
		String result = null;
		try {
			// EDIT 读写文件
			BufferedReader in = new BufferedReader(new InputStreamReader(
					new FileInputStream(path), "UTF-8"));
			String line = in.readLine();
			if (line != null && line.length() > 8) {
				result = line.substring(4, line.length() - 4);
			}
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		return result;
	}

	/**
	 * <li>功能描述：从.wkt文件中读取得到模板最后修改人
	 * 
	 * @param path
	 *            String wkt文件的存放路径
	 * @return result String wkt的模板名称
	 * @author wxk
	 */
	public static String getWktLastModifyUser(String path) {
		String result = null;
		try {
			// EDIT 读写文件
			BufferedReader in = new BufferedReader(new InputStreamReader(
					new FileInputStream(path), "UTF-8"));
			String line = in.readLine();
			line = in.readLine();
			if (line != null && line.length() > 8) {
				result = line.substring(4, line.length() - 3);
			}
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * <li>功能描述：从.wkt文件中读取得到模板名称
	 * 
	 * @param path
	 *            String wkt文件的存放路径
	 * @return result String wkt的模板名称
	 * @author wxk
	 */
	public static String getWktDesName(String path) {
		String result = null;
		try {
			// EDIT 读写文件
			BufferedReader in = new BufferedReader(new InputStreamReader(
					new FileInputStream(path), "UTF-8"));
			String line = in.readLine();
			if (line != null && line.length() >= 8) {
				result = line.substring(4, line.length() - 3);
			}
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * <li>功能描述：读取源文件内容,主要用于图片、媒体文件等二进制文件的读取
	 * 
	 * @param filename
	 *            String 文件路径
	 * @return byte[] 文件内容
	 * @throws IOException
	 * @author wxk
	 */
	public static byte[] readBinaryFile(String filename) throws IOException {

		File file = new File(filename);
		if (filename == null || filename.equals("")) {
			throw new NullPointerException("无效的文件路径");
		}
		long len = file.length();
		byte[] bytes = new byte[(int) len];

		BufferedInputStream bufferedInputStream = new BufferedInputStream(
				new FileInputStream(file));
		int r = bufferedInputStream.read(bytes);
		if (r != len) {
			throw new IOException("读取文件不正确");
		}
		bufferedInputStream.close();

		return bytes;

	}

	/**
	 * <li>功能描述：将数据写入文件，主要用于图片、媒体等二进制文件的写入
	 * 
	 * @param data
	 *            byte[] 数据
	 * @param filename
	 *            String 文件名
	 * @throws IOException
	 * @author wxk
	 */
	public static void writeBinaryFile(byte[] data, String filename)
			throws IOException {
		File file = new File(filename);
		file.getParentFile().mkdirs();
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
				new FileOutputStream(file));
		bufferedOutputStream.write(data);
		bufferedOutputStream.close();

	}

	/**
	 * <li>功能描述： 删除指定文件夹
	 * 
	 * @param folderPath
	 *            String 文件夹路径
	 * @author wxk
	 */
	public static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			File myFilePath = new File(filePath);
			myFilePath.delete(); // 删除空文件夹
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 根据路径删除指定的目录文件，无论存在与否
	 * 
	 * @param sPath
	 *            要删除的目录或文件
	 *@return 删除成功返回 true，否则返回 false。
	 */
	public static boolean DeleteFolder(String sPath) {
		File file = new File(sPath);
		// 判断目录或文件是否存在
		if (!file.exists()) { // 不存在返回 false
			return true;
		} else {
			// 判断是否为文件
			if (file.isFile()) { // 为文件时调用删除文件方法
				return deleteFile(sPath);
			} else {
				// 为目录时返回 false
				return true;
			}
		}
	}

	/**
	 * 删除单个文件
	 * 
	 * @param sPath
	 *            被删除文件的文件名
	 * @return 单个文件删除成功返回true，否则返回false
	 */
	public static boolean deleteFile(String sPath) {
		boolean flag = false;
		File file = new File(sPath);
		// 路径为文件且不为空则进行删除
		if (file.exists() && file.isFile()) {
			file.delete();
			flag = true;
		}
		return flag;
	}

	/**
	 * 删除目录（文件夹）以及目录下的文件
	 * 
	 * @param sPath
	 *            被删除目录的文件路径
	 * @return 目录删除成功返回true，否则返回false
	 */
	public static boolean deleteDirectory(String sPath) {
		// 如果sPath不以文件分隔符结尾，自动添加文件分隔符
		if (!sPath.endsWith(File.separator)) {
			sPath = sPath + File.separator;
		}
		File dirFile = new File(sPath);
		// 如果dir对应的文件不存在，或者不是一个目录，则退出
		if (!dirFile.exists() || !dirFile.isDirectory()) {
			return false;
		}
		boolean flag = true;
		// 删除文件夹下的所有文件(包括子目录)
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			// 删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag)
					break;
			} // 删除子目录
			else {
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag)
					break;
			}
		}
		if (!flag)
			return false;
		// 删除当前目录
		if (dirFile.delete()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * <li>功能描述：删除指定文件夹下所有文件
	 * 
	 * @param path
	 *            String 文件夹路径
	 * @return boolean 操作结果
	 * @author wxk
	 */
	public static boolean delAllFile(String path) {
		boolean flag = false;
		File file = new File(path);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);// 再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * <li>功能描述：批量复制指定路径中的所有文件到指定的目的路径
	 * 
	 * @param srcPath
	 *            String 源文件路径
	 * @param toPath
	 *            String 目的路径
	 * @throws IOException
	 * @author wxk
	 */
	public static void pasteFile(String srcPath, String toPath)
			throws IOException {
		File rootFile = new File(srcPath);
		File[] fileList = rootFile.listFiles();
		if (fileList.length != 0) {
			for (int i = 0; i < fileList.length; i++) {
				byte[] fileByte = readBinaryFile(fileList[i].getPath());
				writeBinaryFile(fileByte, toPath + "\\" + fileList[i].getName());
			}
		}
	}

	/**
	 * 
	 * <li>功能描述：拷贝
	 * 
	 * @param srcFileName
	 *            String 源文件
	 * @param destFileName
	 *            String 目标文件
	 * @return boolean true 成功/false 失败
	 * @throws Exception
	 *             异常
	 * @author wxk
	 */
	public static boolean copy(String srcFileName, String destFileName)
			throws Exception {
		if (srcFileName.endsWith("Thumbs.db")) {
			return true;
		}
		FileInputStream fis = new FileInputStream(new File(srcFileName));
		FileOutputStream fos = new FileOutputStream(new File(destFileName));
		byte[] buf = new byte[1024];
		int i = 0;
		while ((i = fis.read(buf)) != -1) {
			fos.write(buf, 0, i);
		}
		fis.close();
		fos.close();
		return true;
	}

	/**
	 * 
	 * <li>功能描述：建立一个目录
	 * 
	 * @param path
	 *            String 目录
	 * @throws Exception
	 *             出现异常
	 * @return boolean true 成功/false 失败
	 * @author wxk
	 */
	public static boolean mkDir(String path) throws Exception {
		File file = new File(path);
		if (file.isDirectory()) {
			return true;
		}
		if (!file.exists() || file.isFile()) {
			return file.mkdirs();
		}
		return false;
	}

	/**
	 * 
	 * <li>功能描述：拷贝目录，包括子目录
	 * 
	 * @param srcDirName
	 *            String 源目录
	 * @param destDirName
	 *            String 目标目录
	 * @param children
	 *            boolean 是否包含子目录
	 * @return boolean true 成功/false 失败
	 * @throws Exception
	 *             异常
	 * @author wxk
	 */
	public static boolean copyDir(String srcDirName, String destDirName,
			boolean children) throws Exception {
		if (srcDirName.endsWith("CVS")) {
			return true;
		}
		mkDir(destDirName);
		mkDir(srcDirName);
		File file = new File(srcDirName);

		File[] list = file.listFiles();
		for (int i = 0; i < list.length; i++) {
			if (list[i].isDirectory()) {
				if (children) {
					copyDir(srcDirName + "/" + list[i].getName(), destDirName
							+ "/" + list[i].getName(), children);
				}
			} else {
				copy(srcDirName + "/" + list[i].getName(), destDirName + "/"
						+ list[i].getName());
			}
		}
		return true;

	}

	/**
	 * 
	 * <li>功能描述：压缩文件夹
	 * 
	 * @param srcDirName
	 *            String 源文件夹名
	 * @param destFileName
	 *            String 目标文件名
	 * @return boolean true 成功/false 失败
	 * @author wxk
	 */
	public static boolean zipDir(String srcDirName, String destFileName) {
		try {
			File zipFile = new File(destFileName);
			FileOutputStream fos = new FileOutputStream(zipFile);
			ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
					fos, 1024));
			pack(out, srcDirName, "");
			out.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 
	 * <li>功能描述：解压缩文件
	 * 
	 * @param String
	 *            srcFileName 文件名
	 * @param String
	 *            destDirName 目标目录
	 * @return boolean true 成功/false 失败
	 * @author wxk
	 */
	public static boolean unZipFile(String srcFileName, String destDirName) {
		return unZipFile(srcFileName, destDirName, true) == 1;
	}

	/**
	 * <li>功能描述：解压缩文件
	 * 
	 * @param srcFileName
	 *            String 文件名
	 * @param destDirName
	 *            String 目标目录
	 * @param force
	 *            boolean 重名是否覆盖
	 * @return boolean 0 失败/1 成功/2 重名
	 * @author wxk
	 */
	public static int unZipFile(String srcFileName, String destDirName,
			boolean force) {
		try {
			ZipFile zipfile = new ZipFile(srcFileName);
			Enumeration all = zipfile.entries();
			boolean check = force;
			while (all.hasMoreElements()) {
				ZipEntry ze = (ZipEntry) all.nextElement();
				if (!check) {
					List dir = listDir(destDirName);
					for (Iterator i = dir.iterator(); i.hasNext();) {
						String dirName = i.next().toString();
						if (ze.getName().toUpperCase().startsWith(
								dirName.toUpperCase())) {
							return 2;
						}
					}
					check = true;
					unPack(zipfile, ze, destDirName);
				} else {
					unPack(zipfile, ze, destDirName);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
		return 1;
	}

	/**
	 * 
	 * <li>功能描述：获取文件列表。
	 * 
	 * @param String
	 *            path 路径
	 * @return List 文件列表
	 * @author wxk
	 */
	public static List listDir(String path) {
		// System.out.println("list:" + path + " type:" + type);
		File file = new File(path);
		List fileList = new ArrayList();
		if (file.isDirectory()) {
			File[] list = file.listFiles();
			for (int i = 0; i < list.length; i++) {
				if (list[i].isDirectory()) {
					fileList.add(list[i].getName());
				}
			}
		} else {
			return null;
		}
		return fileList;
	}

	/**
	 * 
	 * <li>功能描述：解压缩文件。
	 * 
	 * @param zipfile
	 *            ZipFile 压缩文件对象
	 * @param e
	 *            ZipEntry 压缩实体
	 * @param String
	 *            destDirName 解压缩目录
	 * @return int 操作结果
	 * @throws Exception
	 * @author wxk
	 */
	private static int unPack(ZipFile zipfile, ZipEntry e, String destDirName)
			throws Exception {
		String zipName = e.getName();
		String dirName = zipName.substring(0, zipName.lastIndexOf("/"));
		if (!new File(destDirName + dirName).exists()) {
			new File(destDirName + dirName).mkdirs();
		}
		// System.out.println("zip:" + zipName);
		if (zipName.endsWith("/")) {
			new File(destDirName + zipName).mkdirs();
			return 1;
		}

		FileOutputStream os = new FileOutputStream(destDirName + zipName);
		InputStream is = zipfile.getInputStream(e);
		int n = 0;
		byte[] data = new byte[1024];
		while ((n = is.read(data)) > 0) {
			os.write(data, 0, n);
		}
		is.close();
		os.close();
		return 1;

	}

	/**
	 * 
	 * <li>功能描述：压缩文件。
	 * 
	 * @param out
	 *            ZipOutputStream 压缩文件流
	 * @param srcFileName
	 *            String 原文件名
	 * @param dir
	 *            String 目录
	 * @throws Exception
	 * @author wxk
	 */
	private static void pack(ZipOutputStream out, String srcFileName, String dir)
			throws Exception {
		File tempFile = new File(srcFileName);
		if (tempFile.isDirectory()) {

			File[] list = tempFile.listFiles();
			for (int i = 0; i < list.length; i++) {
				if (dir.equals("")) {
					pack(out, srcFileName + "/" + list[i].getName(), tempFile
							.getName()
							+ "/");
				} else {
					pack(out, srcFileName + "/" + list[i].getName(), dir
							+ tempFile.getName() + "/");
				}
			}
		} else {
			FileInputStream fis = new FileInputStream(tempFile);
			BufferedInputStream origin = new BufferedInputStream(fis, 1024);
			// 为被读取的文件创建压缩条目
			ZipEntry entry = new ZipEntry(dir + tempFile.getName());
			byte[] data = new byte[1024];
			int count;
			// 在向ZIP输出流写入数据之前，必须首先使用out.putNextEntry(entry); 方法安置压缩条目对象
			out.putNextEntry(entry);
			// 向ZIP 文件写入数据
			while ((count = origin.read(data, 0, 1024)) != -1) {
				out.write(data, 0, count);
			}
			origin.close();
			fis.close();
		}
	}

	/**
	 * 
	 * <li>功能描述：保存一个文件
	 * 
	 * @param path
	 *            String 文件名
	 * @param content
	 *            String 文件内容
	 * @return boolean true 成功/false 失败
	 * @author wxk
	 */
	public static boolean saveFile(String path, String content) {
		try {
			// EDIT 读写文件
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(path), "UTF-8"));
			out.write(content);
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

}